package com.commutersconnect.snippet

import scala.xml.{NodeSeq, Text}
import net.liftweb._
import util._
import common._
import http.js.JsCmds.{Alert, Noop, FocusOnLoad}
import http.js.JE._
import http.{S, SHtml}
import java.util.Date
import com.commutersconnect.lib._
import Helpers._

import com.commutersconnect.model.{ReportStatus, Report, Message, User}

//We will have need of exposing the url for the view page to other portions of
//our application.  To that end, we keep the logic for constructing the menu
//item next to a method that will return a string that links to the menu.  (I
//looked briefly for a way to more closely link these two with no success.  In
//the end, I am happy with the logic for this being kept so close together as
//to not be worried by it.)
object ViewReportSnippet {
  import sitemap._
  val siteMenu =
        Menu.param[Report](
          "Report",
          "Report",
          s => Report.findByKey(s.toInt),
          pi => pi.id.toString) / "report";

  def viewReportUrl(report:Report) = "/report/%s".format(report.id.is)
}


// This snippet requires a Report to be of any use.  So it is provided on
// creation to us.
class ShowReport(report: Report) {
  def render = {
    import com.commutersconnect.util.DateUtils.toPrettyString

    //We use the lat and long of this report to make the URL that is looked up
    //through google.  We could (should?) probably push this down to the
    //client for calculation.
    val url = imgUrl(report.latitude, report.longitude)


    //In addition to placing all of the information, we also remove all
    //elements styled "mockup".
    //The tricky parts of this section include the logic that sets the report
    //image and the logic around submitting comments.
    SHtml.idMemoize( fullPage => {
    ".mockup" #> "" &
    "#reportStatus *" #> report.status &
    "#reportedDate *" #> toPrettyString(report.createdAt, now) &
    "#reportedDate [alt]" #> report.createdAt &
    "#reportSubject *" #> report.subject &
    "#reportText *" #> report.text &
    (if (!report.images.isEmpty) {
      "#reportImage [src]" #> "/report/%s/image".format(report.id.toString)}
      else {
       "#reportImage" #> ""
      }) &
    "#map_canvas" #> <img src={url} alt="Image location."/> &
    "#comments" #> SHtml.idMemoize( comments => {
      //We start the comments section with a newly created comment for this
      //report with the current user as the author.  If it is submitted and
      //saved successfully, the section is updated and a new comment is
      //created.
      val newMessage = Message.create.report(report)
      User.currentUser.foreach(newMessage.author(_))

      //We also need to refresh our list of messages.  Pointless on the first
      //run through this, but necessary on the replace call.  (That is,
      //without the refresh you will not see the comment you just posted.)
      report.messages.refresh

      ".mockup" #> "" & //Since idMemoize keeps mockups, we keep removing them.
      ".comment" #> report.messages.reverse.map(message => {
          ".author *" #> (message.author map (_.firstName.get) openOr "anonymous") &
          ".date *" #> toPrettyString(message.createdAt, now) &
          ".date [alt]" #> message.createdAt &
          ".text *" #> message.text
        }) &
      "#newComment" #> SHtml.textarea(newMessage.text, newMessage.text(_)) &
      "#postComment" #> SHtml.ajaxSubmit("Post", () => {
        newMessage.validate match {
          case Nil =>
            newMessage.save
            comments.setHtml
          case errors =>
            S.error(errors)
            Noop
        }
      }) &
      "#changeStatus" #> {
        //We have several things to consider for the change status button.
        //First, we only let logged in users change the status.
        //Second, it is the "change" status button.  So, we may be letting you
        //open or close an issue.

        //So, first we make a way to determine the submit text and resulting
        //status.
        def applicableAction(cur:ReportStatus.Value) =
          if (cur == ReportStatus.open) ("Close", ReportStatus.closed) else ("Open", ReportStatus.open)


        User.currentUser.map( curUser=>{
          SHtml.ajaxSubmit(applicableAction(report.status.is)._1, () => {
            //Closing a report is identical to saving a message, but will also
            //change the status.  TODO Consider pulling similar logic out?
            newMessage.validate match {
              case Nil =>
                newMessage.save
                report.status(applicableAction(report.status.is)._2)
                report.save
                fullPage.setHtml//In this case, we reload the full page...
              case errors =>
                S.error(errors)
                Noop
            }
          })
        }).openOr(NodeSeq.Empty)
      }
    })
    })
  }

  //To get the image url for this, we make a call over to the Google Maps
  //API.
  def imgUrl(lat:Double, lng:Double) = {
    val latLng = "%s,%s".format(lat.toString, lng.toString)
    "//maps.googleapis.com/maps/api/staticmap?center=%s&markers=%s&zoom=16&size=250x250&maptype=roadmap&sensor=false".format(latLng, latLng)
  }
}

